home *** CD-ROM | disk | FTP | other *** search
- /* Routines for AX.25 encapsulation in KISS TNC
- * Copyright 1991 Phil Karn, KA9Q
- *
- * Modified by G1EMM 19/11/90 to support multi-port KISS mode.
- */
- /* Mods by G1EMM */
-
- #include "global.h"
- #include "commands.h"
- #include "mbuf.h"
- #include "iface.h"
- #include "kiss.h"
- #include "devparam.h"
- #include "slip.h"
- #include "asy.h"
- #include "pktdrvr.h"
- #include "kisspoll.h"
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: kiss.c,v 1.17 1997/01/19 21:13:05 root Exp root $";
- #endif
-
- static int kiss_stop (struct iface * iface);
-
- #ifdef POLLEDKISS
- /* this line is to fake out the linker */
- void *polledkiss_fakeit = (void *) kiss_poller; /*lint !e611 */
- #endif
-
-
- /* Send raw data packet on KISS TNC */
- int
- kiss_raw (struct iface *iface, struct mbuf *data)
- {
- register struct mbuf *bp;
-
- /* Put type field for KISS TNC on front */
- if ((bp = pushdown (data, 1)) == NULLBUF) {
- free_p (data);
- return -1;
- }
- bp->data[0] = PARAM_DATA;
- bp->data[0] |= uchar (iface->port << 4); /*lint !e701 */
- if (iface->port) {
- iface->rawsndcnt++;
- iface->lastsent = secclock ();
- }
- /* slip_raw also increments sndrawcnt */
- (void) slip_raw (Slip[iface->xdev].iface, bp);
- return 0;
- }
-
-
-
- /* Process incoming KISS TNC frame */
- void
- kiss_recv (struct iface *iface, struct mbuf *bp)
- {
- char kisstype;
- struct iface *kissif;
- int port;
- struct mbuf **bpp = &bp;
- #ifdef RXECHO
- struct mbuf *bbp;
- #endif
-
-
- kisstype = (char) PULLCHAR (bpp);
- port = kisstype >> 4; /*lint !e702 */
-
- if ((kissif = Slip[iface->xdev].kiss[port]) == NULLIF) {
- free_p (bp);
- return;
- }
- switch (kisstype & 0xf) {
- case PARAM_DATA:
- #ifdef RXECHO
- /* Now we can echo the packet if configured (see config.c) */
- if (kissif->rxecho) {
- (void) dup_p (&bbp, bp, 0, len_p (bp));
- (void) (*kissif->rxecho->raw) (kissif->rxecho, bbp);
- }
- #endif
- ax_recv (kissif, bp);
- break;
- default:
- free_p (bp);
- break;
- }
- }
-
-
-
- /* Perform device control on KISS TNC by sending control messages */
- int32
- kiss_ioctl (struct iface *iface, int cmd, int set, int32 val)
- {
- struct mbuf *hbp;
- char *cp;
- int32 rval = 0L;
-
- /* At present, only certain parameters are supported by
- * stock KISS TNCs. As additional params are implemented,
- * this will have to be edited
- */
- switch (cmd) {
- case PARAM_RETURN:
- case PARAM_RETURN2:
- set = 1;/* Note fall-thru */
- case PARAM_TXDELAY:
- case PARAM_PERSIST:
- case PARAM_SLOTTIME:
- case PARAM_TXTAIL:
- case PARAM_FULLDUP:
- case PARAM_HW:
- if (!set) {
- rval = -1; /* Can't read back */
- break;
- }
- /* Allocate space for cmd and arg */
- if ((hbp = alloc_mbuf (2)) == NULLBUF) {
- free_p (hbp);
- rval = -1;
- break;
- }
- cp = (char *) hbp->data;
- *cp++ = (char) cmd;
- *cp = (char) val;
- hbp->cnt = 2;
- if (hbp->data[0] != (unsigned char) PARAM_RETURN)
- hbp->data[0] |= uchar(iface->port << 4); /*lint !e701 */
- if (iface->port) {
- iface->rawsndcnt++;
- iface->lastsent = secclock ();
- }
- /* Even more "raw" than kiss_raw */
- (void) slip_raw (Slip[iface->xdev].iface, hbp);
- rval = val;
- break;
- case PARAM_SPEED: /* These go to the local asy driver */
- case PARAM_DTR:
- case PARAM_RTS:
- case PARAM_UP:
- case PARAM_DOWN:
- #ifdef UNIX
- case PARAM_MIN:/* almost certainly not its intended use... */
- #endif
- rval = asy_ioctl (iface, cmd, set, val);
- break;
- default: /* Not implemented */
- rval = -1;
- break;
- }
- return rval;
- }
-
-
-
- static int
- kiss_stop (struct iface *iface)
- {
- Slip[iface->xdev].kiss[iface->port] = NULLIF;
- return 0;
- }
-
-
-
- /* Attach a kiss interface to an existing asy interface in the system
- * argv[0]: hardware type, must be "kiss"
- * argv[1]: master interface, e.g., "ax4"
- * argv[2]: kiss port, e.g., "4"
- * argv[3]: interface label, e.g., "ax0"
- * argv[4]: maximum transmission unit, bytes
- */
- int
- kiss_attach (int argc, char **argv, void *p OPTIONAL)
- {
- struct iface *if_asy, *if_kiss;
- int port;
-
- if ((if_asy = if_lookup (argv[1])) == NULLIF) {
- tprintf ("Interface %s does not exist\n", argv[1]);
- return -1;
- }
- /* Check for ASY type interface ! - WG7J */
- if (if_asy->type != CL_AX25) {
- tprintf ("Multidrop KISS not allowed in interface: %s\n", argv[1]);
- return -1;
- }
- if (if_lookup (argv[3]) != NULLIF) {
- tprintf ("Interface %s already exists\n", argv[4]);
- return -1;
- }
- if ((port = atoi (argv[2])) == 0) {
- tprintf ("Port 0 automatically assigned to interface %s\n", argv[1]);
- return -1;
- }
- if (port < 1 || port > 15) {
- tputs ("Ports 1 to 15 only\n");
- return -1;
- }
- if (Slip[if_asy->xdev].kiss[port] != NULLIF) {
- tprintf ("Port %d already allocated on interface %s\n", port, argv[1]);
- return -1;
- }
- /* Create interface structure and fill in details */
- if_kiss = (struct iface *) callocw (1, sizeof (struct iface));
-
- if_kiss->addr = if_asy->addr;
- if_kiss->name = strdup (argv[3]);
-
- if (argc >= 5)
- if_kiss->mtu = (int16) atoi (argv[4]);
- else
- if_kiss->mtu = if_asy->mtu;
-
- if_kiss->iface_metric = 1;
- if_kiss->dev = if_asy->dev;
- if_kiss->stop = kiss_stop;
- (void) setencap (if_kiss, "AX25");
- if_kiss->ioctl = kiss_ioctl;
- if_kiss->raw = kiss_raw;
- if (if_kiss->hwaddr == NULLCHAR)
- if_kiss->hwaddr = mallocw (AXALEN);
- if (if_kiss->ipcall == NULLCHAR)
- if_kiss->ipcall = mallocw (AXALEN);
- memcpy (if_kiss->ipcall, Mycall, AXALEN);
- memcpy (if_kiss->hwaddr, Mycall, AXALEN);
- if_kiss->xdev = if_asy->xdev;
- if_kiss->next = Ifaces;
- Ifaces = if_kiss;
- if_kiss->port = port;
- Slip[if_kiss->xdev].kiss[if_kiss->port] = if_kiss;
- return 0;
- }
-